package cn.hh.ymcc.mq.consumer;


import cn.hh.ymcc.domain.PayOrder;
import cn.hh.ymcc.dto.Order2payOrderParamDto;
import cn.hh.ymcc.service.IPayOrderService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

@Component
// 交给容器管理   consumerGroup = 消费者组名    topic = 生产者的中topic  selectorExpression = 生产者中的tags   messageModel.CLUSTERING = 消费消息的模式是集群: 一个消费只会被一个消费者消息
@RocketMQMessageListener(consumerGroup = "service-pay-consumer", topic = "topic-order", selectorExpression = "tag-order", messageModel = MessageModel.CLUSTERING)
public class PayOrderConsumer implements RocketMQListener<MessageExt> {

    @Autowired
    private IPayOrderService payOrderService; // 注入

    /**
     * 消息一定要处理幂等性  自动签收消息
     * 只要我们的方法不抛出异常,MQ就默认为消费成功,那么就会标记已消费,不在投递了
     * 如果我们方法中抛出异常,那么MQ就认为没有消费成功,过一会还好投递消息给你
     *
     * @param messageExt
     */

    @Override
    public void onMessage(MessageExt messageExt) {
        if (messageExt.getBody() == null) { // 防御性编程
            return;
        }
        // 调用messageExt.getBody()获取到消息体, 将获取到的消息体转成字符串类型对象jsonStr
        // 真正消费消息的业务逻辑
        String message = new String(messageExt.getBody(), StandardCharsets.UTF_8);
        // 将字符串类型的消息体对象jsonStr,转换为Order2payOrderParamDto类型
        Order2payOrderParamDto orderDto = JSONObject.parseObject(message, Order2payOrderParamDto.class);

        // 我们需要保证消费消息的幂等性, 一个消息只能被成功消费一次, 只能保存一个支付单
        Wrapper<PayOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("order_no", orderDto.getOrderNo());
        PayOrder payOrder = payOrderService.selectOne(wrapper);
        if (payOrder != null) {
            return; // 自动签收,以后不要在发送消息了
        }
        // 消费消息,保存支付单
        payOrderService.savePayOrder(orderDto);

    }

}
